#include "wo_routine.h"
#include <stdio.h>
#include <string.h>
#include <threads.h>
#include <time.h>
#define UNUSED(param) (void)(param)

void co1(void *args) {
  UNUSED(args);
  thrd_t t = thrd_current();
  for (int n = 5; n >= 0; n -= 2) {
    thrd_sleep(&(struct timespec){.tv_nsec = 10000000}, NULL);
    printf("thrd: %lu co1: n=%d\n", t, n);
    wo_yield();
  }
  return;
}

void co2(void *args) {
  UNUSED(args);
  thrd_t t = thrd_current();
  for (int n = 4; n >= 0; n -= 2) {
    thrd_sleep(&(struct timespec){.tv_nsec = 10000000}, NULL);
    printf("thrd: %lu co2: n=%d\n", t, n);
    wo_yield();
  }
  return;
}

void greeting(void *args) {
  for (int i = 0; i < 6; i++) {
    wo_yield();
  }
  printf("greeting: %s", (const char *)args);
  return;
}

int thrd1(void *args) {
  UNUSED(args);
  wo_start(co1, NULL);
  wo_start(co2, NULL);
  wo_start(greeting, "Hello world!\n");
  wo_main();
  return 0;
}

int thrd2(void *args) {
  UNUSED(args);
  wo_start(co1, NULL);
  wo_start(co2, NULL);
  wo_start(greeting, "Hello world!\n");
  wo_main();
  return 0;
}

void run_single(void) {
  wo_start(co1, NULL);
  wo_start(co2, NULL);
  wo_start(greeting, "Hello world!\n");
  wo_main();
  printf("run single end.\n");
}

void run_parallels(void) {
  thrd_t t1, t2;
  thrd_create(&t1, thrd1, NULL);
  thrd_create(&t2, thrd2, NULL);
  thrd_join(t1, NULL);
  thrd_join(t2, NULL);
  printf("run parallels end.\n");
}

int main(int argc, const char *argv[]) {
  if (argc > 1) {
    if (strncmp(argv[1], "parallel", strlen("parallel")) == 0) {
      run_parallels();
      return 0;
    } else if (strncmp(argv[1], "single", strlen("single")) == 0) {
      run_single();
      return 0;
    }
  }

  printf("%s <parallel|single>\n", argv[0]);
  return 0;
}
